package com.star.common.orm.config;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.star.common.orm.plugin.InsertIgnorePlugin;
import com.star.common.orm.typehandlers.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * Mybatis 配置
 *
 * @author
 **/
@Slf4j
@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructor
@EnableTransactionManagement
public class MybatisPlusConfig implements InitializingBean {

    private final MybatisPlusProperties mybatisPlusProperties;
    private final List<JsonStringTypeHandler> jsonStringTypeHandlers;

    /**
     * INSERT IGNORE 改写插件
     */
    @Bean
    @ConditionalOnMissingBean
    public InsertIgnorePlugin insertIgnorePlugin() {
        return new InsertIgnorePlugin();
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        log.info("分页插件加载成功");
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 阻断插件,防止全表更新，删除，全表更新危害太大了，涉及到这种的建议使用手写sql直接db层面运行
        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
        return interceptor;
    }

    @Override
    public void afterPropertiesSet() {
        MybatisConfiguration configuration = mybatisPlusProperties.getConfiguration();
        if (configuration == null) {
            configuration = new MybatisConfiguration();
            mybatisPlusProperties.setConfiguration(configuration);
        }
        if (configuration.getLogImpl() == null) {
            configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        }
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        typeHandlerRegistry.register(BigDecimal.class, new BigDecimalTypeHandler());
        typeHandlerRegistry.register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
        typeHandlerRegistry.register(String[].class, new StringsTypeHandler());
        typeHandlerRegistry.register(Long[].class, new LongsTypeHandler());
        typeHandlerRegistry.register(Double[].class, new DoublesTypeHandler());
        typeHandlerRegistry.register(Integer[].class, new IntegersTypeHandler());
        typeHandlerRegistry.register(Map.class, new MapTypeHandler());
        typeHandlerRegistry.register(Map[].class, new MapsTypeHandler());
        // JavaObject、JavaArray
        if (CollUtil.isNotEmpty(jsonStringTypeHandlers)) {
            for (JsonStringTypeHandler jsonStringTypeHandler : jsonStringTypeHandlers) {
                typeHandlerRegistry.register(jsonStringTypeHandler.type(), jsonStringTypeHandler);
            }
        }
    }

    /**
     * 如果是对全表的删除或更新操作，就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
     */
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
        return new BlockAttackInnerInterceptor();
    }

}
